﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.Networking;
using UnityEngine.UI;
using cframework_xlua;
using System;


public class HotUpdate : BaseHotUpdate
{
    public Text progressText;
    public Text progressPercent;
    public Slider progressSlider;
    public GameObject errorDlg;
    public Button retryBtn;
    public Text errorDlgContent;
    public GameObject downloadDlg;
    public Button downloadBtn;
    public Text downloadDlgContent;
    public bool enableDownloadDialog;
    public Text versionText;


    float hotupdateTaskWeight = 90;
    float waitTaskWeight = 10;
    float waitTaskTime = 1;
    float totalWeight = 100;
    
    protected IEnumerator Start()
    {
        totalWeight = hotupdateTaskWeight + waitTaskWeight;

        errorDlg.SetActive(false);
        downloadDlg.SetActive(false);
        
        progressPercent.text = "0%";
        progressText.text = "";
        progressSlider.value = 0;

        if (!AppManager.GetAppInfo().enable_hotupdate)
        {
            var task = CodeLoadTask.StartGame().WithResult();
            yield return task;
            var startGameResult = (bool)task.Current;
            if (!startGameResult)
            {
                errorDlg.SetActive(true);
                retryBtn.onClick.RemoveAllListeners();
                errorDlgContent.text = "CodeLoadTask.StartGame failed";
                yield return new WaitUntil(() => errorDlg.activeSelf == false);
            }
        }
        else
        {
            InitHotUpdateInfo();
            
            UpdateProgressUI();


            if(global::StartHotUpdate.GetRunningHotUpdateCodeVersion() < 0)
            {
                var task = global::StartHotUpdate.CallEnterGameAsync().WithResult();
                yield return task;
                var enterGameResult = (bool)task.Current;
                if(!enterGameResult)
                {
                    errorDlg.SetActive(true);
                    retryBtn.onClick.RemoveAllListeners();
                    retryBtn.onClick.AddListener(() => { errorDlg.SetActive(false); });
                    errorDlgContent.text = "StartHotUpdate.CallEnterGame failed";
                    yield return new WaitUntil(() => errorDlg.activeSelf == false);
                }
            }
            else
            {
                var task = StartHotUpdate().WithResult();
                yield return task;
                var hotfixResult = (bool)task.Current;
                if(!hotfixResult)
                {
                    errorDlg.SetActive(true);
                    retryBtn.onClick.RemoveAllListeners();
                    retryBtn.onClick.AddListener(() => { errorDlg.SetActive(false); });
                    errorDlgContent.text = "StartHotUpdate failed";
                    yield return new WaitUntil(() => errorDlg.activeSelf == false);
                }

                var waitTask = WaitTask().WithResult();
                yield return waitTask;
                var waitTaskResult = (bool)waitTask.Current;
                if (!waitTaskResult)
                {
                    errorDlg.SetActive(true);
                    retryBtn.onClick.RemoveAllListeners();
                    retryBtn.onClick.AddListener(() => { errorDlg.SetActive(false); });
                    errorDlgContent.text = "WaitTask failed";
                    yield return new WaitUntil(() => errorDlg.activeSelf == false);
                }

                var startGameTask = CodeLoadTask.StartGame().WithResult();
                yield return startGameTask;
                var startGameResult = (bool)startGameTask.Current;
                if (!startGameResult)
                {
                    errorDlg.SetActive(true);
                    retryBtn.onClick.RemoveAllListeners();
                    retryBtn.onClick.AddListener(() => { errorDlg.SetActive(false); });
                    errorDlgContent.text = "CodeLoadTask.StartGame failed";
                    yield return new WaitUntil(() => errorDlg.activeSelf == false);
                }
            }
        }

        if (this != null)
        {
            UnityEngine.SceneManagement.SceneManager.UnloadSceneAsync(this.gameObject.scene);
        }
    }


    
    
    void Update()
    {
        float rate = hotupdateTaskWeight / totalWeight;
        float percent = 0;
        long total = 0;
        long current = 0;
        float downloadSpeed = 0;
        if(UpdateDownloadProgress(out percent, out total, out current, out downloadSpeed))
        {
            progressSlider.value = percent * rate;
            progressPercent.text = (int)(percent * rate * 100) + "%";
        }
    }

    void UpdateProgressUI()
    {
        float rate = hotupdateTaskWeight / totalWeight;
        var task = GetCurTask();
        if(task == null)
        {
            return;
        }
        
        var key = task.ToKey();
        float percent = (System.Int32)sumProgressMap[key] / (float)totalProgress;
        progressSlider.value = percent * rate;
        progressPercent.text = (int)(percent * rate * 100) + "%";


        progressText.text = GetTaskStatusTip();

        UpdateVersionText();
    }

    string GetTaskStatusTip()
    {
        var task = GetCurTask();
        if (task == null)
        {
            return null;
        }

        return task.taskType + "| " + task.status;
    }




    IEnumerator WaitTask()
    {
        float startTime = Time.time;
        float endTime = startTime + waitTaskTime;

        while (Time.time < endTime)
        {
            yield return null;

            float percent = (hotupdateTaskWeight + (Time.time - startTime) / (endTime - startTime) * waitTaskWeight) / totalWeight;
            progressSlider.value = percent;
            progressPercent.text = (int)(percent * 100) + "%";
        }

        progressSlider.value = 1;
        progressPercent.text = 100 + "%";
        
        yield return true;
    }


    IEnumerator StartHotUpdate(float waitStepTime = 0)
    {
        while (true)
        {
            MoveNextTaskIfDone();
            UpdateProgressUI();

            yield return new WaitForSeconds(waitStepTime);

            var hotUpdateTask = ProcessHotUpdate().WithResult();
            yield return hotUpdateTask;
            var result = (object[])hotUpdateTask.Current;

            var finalResult = (bool)result[0];
            var tempResult = (bool)result[1];

            UpdateProgressUI();

            if (finalResult)
            {
                yield return true;
            }
            else
            {
                if (tempResult)
                {
                    if (enableDownloadDialog)
                    {
                        var task = GetCurTask();
                        if (useOldLogic)
                        {
                            if (task != null && task.taskType == TaskType.code_check && task.status == TaskStatus.done)
                            {
                                int totalSize = 0;
                                int downloadedSize = 0;
                                HotUpdateDllMgr.GetDownloadProgress(out totalSize, out downloadedSize);
                                if (totalSize > 0)
                                {
                                    downloadDlg.SetActive(true);
                                    downloadDlgContent.text = "下截" + CommonUtil.toSizeString(totalSize);
                                }
                            }
                            else if (task != null && task.taskType == TaskType.addressable_check && task.status == TaskStatus.done)
                            {
                                long needDownloadSize = HotUpdateAddressableMgr.GetNeedDownloadSize();
                                if (needDownloadSize > 0)
                                {
                                    downloadDlg.SetActive(true);
                                    downloadDlgContent.text = "下截" + CommonUtil.toSizeString(needDownloadSize);
                                }
                            }
                        }
                        else
                        {
                            if (task != null && task.taskType == TaskType.addressable_check && task.status == TaskStatus.done)
                            {
                                int totalSize = 0;
                                int downloadedSize = 0;
                                HotUpdateDllMgr.GetDownloadProgress(out totalSize, out downloadedSize);

                                long needDownloadSize = HotUpdateAddressableMgr.GetNeedDownloadSize();
                                if (needDownloadSize + totalSize > 0)
                                {
                                    downloadDlg.SetActive(true);
                                    downloadDlgContent.text = "下截" + CommonUtil.toSizeString(needDownloadSize + totalSize);
                                }
                            }
                        }
                    }

                    if (downloadDlg.activeSelf)
                    {
                        downloadBtn.onClick.RemoveAllListeners();
                        downloadBtn.onClick.AddListener(() => { downloadDlg.SetActive(false); });

                        yield return new WaitUntil(() => downloadDlg.activeSelf == false);
                    }
                }
                else
                {
                    errorDlgContent.text = GetTaskStatusTip();
                    retryBtn.onClick.RemoveAllListeners();
                    retryBtn.onClick.AddListener(() =>
                    {
                        errorDlg.SetActive(false);
                    });

                    errorDlg.SetActive(true);
                    yield return new WaitUntil(() => errorDlg.activeSelf == false);
                }
            }
        }
    }


    void UpdateVersionText()
    {
        string a = "";
        var repository_version = AppManager.GetAppInfo().repository_version;
        string b = "";
        if (!string.IsNullOrEmpty(repository_version))
        {
            b = repository_version.Substring(0, Mathf.Min(repository_version.Length, 5)) + "-" + AppManager.GetAppInfo().repository_version.Substring(Mathf.Max(0, repository_version.Length - 5));
        }

        string space = "  ";
        a += AppManager.GetAppInfo().branch_name + space + b + "\n";
        a += Application.version + space + AppManager.GetAppInfo().hotupdate_version + space + AppManager.GetAppInfo().publish_type + "\n";
        a += WhiteDeviceMgr.isWhite() + space + global::StartHotUpdate.GetRunningHotUpdateCodeVersion() + space + HotUpdateDllMgr.GetLatestVersion() + space + HotUpdateAddressableMgr.GetLatestVersion() + "\n";

        versionText.text = a;
    }



    //Vector2 scrollPos;
    //int showMode;
    //void OnGUI()
    //{
    //    InitGUI_Size();

    //    scrollPos = GUILayout.BeginScrollView(scrollPos);




    //    if(GUILayout.Button("showMode: " + showMode))
    //    {
    //        showMode++;
    //        showMode %= 3;
    //    }


    //    if(showMode == 1)
    //    {
    //        ShowStaticInfo();
    //        var task = GetCurTask(true);
    //        if(task != null)
    //        {
    //            GUILayout.Label("status: " + task.taskType + " | " + task.status);
    //            switch(task.status)
    //            {
    //                case TaskStatus.failed:
    //                {
    //                    if(showMode == 1)
    //                    {
    //                        if(GUILayout.Button("start hotupdate"))
    //                        {
    //                            //StartHotUpdate();
    //                        };
    //                    }
    //                }
    //                break;
    //            }
    //        }
    //    }
    //    else if(showMode == 2)
    //    {
    //        ShowSample();
    //    }



    //    GUILayout.EndScrollView();
    //}


}
